package com.jic.order.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.jic.common.base.vo.Page;
import com.jic.common.base.vo.PageResult;
import com.jic.common.base.vo.RestResult;
import com.jic.order.base.BaseService;
import com.jic.order.entity.*;
import com.jic.order.enums.OperatorActionEnum;
import com.jic.order.enums.OrderTagEnum;
import com.jic.order.manage.response.OrderResponse;
import com.jic.order.mapper.OrderInvoiceMapper;
import com.jic.order.mapper.OrderMapper;
import com.jic.order.mapper.OrderMarkMapper;
import com.jic.order.mapper.OrderParentMapper;
import com.jic.order.model.OrderModel;
import com.jic.order.model.domain.OperateModel;
import com.jic.order.model.entity.MOrderBale;
import com.jic.order.request.OrderNoPage;
import com.jic.order.request.OrderQueryPage;
import com.jic.order.request.OrderStatisticsRequest;
import com.jic.order.request.OrderTagRequest;
import com.jic.order.response.OrderClosedInfo;
import com.jic.order.response.OrderInfo;
import com.jic.order.response.OrderInvoceInfo;
import com.jic.order.response.OrderMarkInfo;
import com.jic.order.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单主表
 *
 * @author : yinhaijun
 * @version : v1.0.0
 * @email :
 * @since : 2020-01-13 06:17:06
 */
@Service
public class OrderServiceImpl extends BaseService implements OrderService {

	@Resource
	private OrderMapper orderMapper;

	@Resource
	private OrderParentMapper orderParentMapper;

	@Resource
	private OrderMarkMapper orderMarkMapper;

	@Autowired
	private OrderGoodsService orderGoodsService;

	@Autowired
	private OrderProcessLogService orderProcessLogService;

	@Resource
	private OrderInvoiceMapper orderInvoiceMapper;

	@Resource
    private OrderPayDetailService orderPayDetailService;

	@Resource
    private OrderAfterSaleApplyService orderAfterSaleApplyService;



	@Override
	public PageResult<Order> queryPage(OrderQueryPage orderQueryPage) {
		Order order = new Order();
		BeanUtils.copyProperties(orderQueryPage, order);

		// 计算下标
		int startIndex = (orderQueryPage.getStart() - 1) * orderQueryPage.getLimit();
		List<Order> list = orderMapper.queryPage(startIndex, orderQueryPage);
		long count = orderMapper.queryPageCount(orderQueryPage);

		PageResult pageResult = new PageResult();
		pageResult.setTotal(count);
		pageResult.setRows(list);
		return pageResult;
	}
    @Override
    public PageInfo<Order> queryPageOrder(OrderQueryPage orderQueryPage) {
		PageHelper.startPage( (orderQueryPage.getStart() - 1) * orderQueryPage.getLimit(), orderQueryPage.getLimit());
        // 计算下标
        //int startIndex = (orderQueryPage.getStart() - 1) * orderQueryPage.getLimit();
        List<Order> list = orderMapper.queryPageOrder(orderQueryPage);
		PageInfo pageInfo = new PageInfo(list);
		PageResult<Order> result = new PageResult<>();
		result.setTotal(pageInfo.getTotal());
		result.setRows(list);
        return new PageInfo(list);
    }

	@Override
	public RestResult<OrderInfo> info(String orderNo) {
		return executeQuery(() -> {
			if (StringUtils.isEmpty(orderNo)) {
				return null;
			}
			Order order = new Order();
			order.setOrderNo(orderNo);
			List<Order> orderList = orderMapper.query(order);
			if (null != orderList && orderList.size()>0) {
				OrderInfo orderInfo = new OrderInfo();
				BeanUtils.copyProperties(orderList.get(0), orderInfo);

				OrderParent orderParent = new OrderParent();
				orderParent.setParentOrderNo(orderList.get(0).getParentOrderNo());
				List<OrderParent> orderParentList = orderParentMapper.query(orderParent);
				if (null != orderParentList) {
					BeanUtils.copyProperties(orderParentList.get(0), orderInfo);
					orderInfo.setReceiverProvinceName(orderParentList.get(0).getReceiverProvinceName());
					orderInfo.setReceiverCityName(orderParentList.get(0).getReceiverCityName());
					orderInfo.setReceiverRegionName(orderParentList.get(0).getReceiverRegionName());
				}
				return orderInfo;
			}
			return null;
		});
	}

	@Override
	public RestResult<PageResult<OrderGoods>> queryOrderGoods(OrderNoPage orderNoPage) {
		return executeQuery(() -> {
			OrderGoods orderGoods = new OrderGoods();
			orderGoods.setOrderNo(orderNoPage.getOrderNo());
			Page page = new Page();
			page.setLimit(orderNoPage.getLimit());
			page.setStart(orderNoPage.getStart());
			return orderGoodsService.queryPage(orderGoods, page);
		});
	}

	@Override
	public RestResult<PageResult<OrderProcessLog>> orderProcessLogQuery(OrderNoPage orderNoPage) {
		return executeQuery(() -> {
			OrderProcessLog orderProcessLog = new OrderProcessLog();
			orderProcessLog.setOrderNo(orderNoPage.getOrderNo());
			Page page = new Page();
			page.setLimit(orderNoPage.getLimit());
			page.setStart(orderNoPage.getStart());
			return orderProcessLogService.queryPage(orderProcessLog, page);
		});
	}

    @Override
    public RestResult<PageResult<OrderPayDetail>> orderPayDetailQuery(OrderNoPage orderNoPage) {
        return executeQuery(() -> {
            OrderPayDetail orderPayDetail = new OrderPayDetail();
            orderPayDetail.setOrderPayNo(orderNoPage.getOrderNo());
            Page page = new Page();
            page.setLimit(orderNoPage.getLimit());
            page.setStart(orderNoPage.getStart());
            return orderPayDetailService.queryPage(orderPayDetail, page);
        });
    }

    @Override
    public RestResult<PageResult<OrderAfterSaleApplyModel>> orderAfterSaleApplyQuery(OrderNoPage orderNoPage) {
        return executeQuery(() -> {
            OrderAfterSaleApplyModel orderAfterSaleApplyModel = new OrderAfterSaleApplyModel();
            orderAfterSaleApplyModel.setOrderNo(orderNoPage.getOrderNo());
            Page page = new Page();
            page.setLimit(orderNoPage.getLimit());
            page.setStart(orderNoPage.getStart());
            return orderAfterSaleApplyService.queryPage(orderAfterSaleApplyModel, page);
        });
    }

	@Override
	public List<JSONObject> queryMOrderByDate(JSONObject jsonObject) {
		return null;
	}

	/**
	 * 根据订单号查询订单
	 * @param parent_order_no
	 * @return
	 */
	@Override
	public List<JSONObject> queryOrderByOrderNo(String parent_order_no) {
		return orderMapper.queryOrderByOrderNo(parent_order_no);
	}

	@Override
	public long insert(Order order) {
		return orderMapper.insert(order);
	}

	@Override
	public long delete(Long id) {
		return 0;
	}

	@Override
	public long update(Order order) {
		return orderMapper.update(order);
	}

	@Override
	public Integer updateByOrderNo(JSONObject jsonObject) {
		return orderMapper.updateByOrderNo(jsonObject);
	}

	@Override
	public Integer insertOrderSettlement(JSONObject jsonObject) {
		return orderMapper.insertOrderSettlement(jsonObject);
	}

	@Override
	public Integer updateOrderSettlement(JSONObject jsonObject) {
		return orderMapper.updateOrderSettlement(jsonObject);
	}

	@Override
	public Integer insertScoreRecord(JSONObject ret) {
		return orderMapper.insertScoreRecord(ret);
	}

	@Override
	public Integer updateScoreRecord(JSONObject ret) {
		return orderMapper.updateScoreRecord(ret);
	}

	@Override
    public RestResult<MOrderBale> getParcel(String orderNo) {
        return null;
    }


    @Override
	public RestResult<OrderClosedInfo> orderClosedInfoQuery(OrderNoPage orderNoPage) {
		return executeQuery(() -> {
			OrderProcessLog orderProcessLog = new OrderProcessLog();
			orderProcessLog.setOperator(OperatorActionEnum.CLOSED.getCode());
			orderProcessLog.setOrderNo(orderNoPage.getOrderNo());
			List<OrderProcessLog> orderProcessLogList = orderProcessLogService.query(orderProcessLog);
			if (null != orderProcessLogList && !orderProcessLogList.isEmpty()) {
				OrderClosedInfo orderClosedInfo = new OrderClosedInfo();
				orderClosedInfo.setCloser(orderProcessLogList.get(0).getOperatorName());
				orderClosedInfo.setCloseTime(orderProcessLogList.get(0).getOperatorTime());
				orderClosedInfo.setReason(orderProcessLogList.get(0).getOperatorLog());
				return orderClosedInfo;
			}
			return null;
		});
	}

	@Override
	public RestResult<OrderMarkInfo> markQuery(OrderNoPage orderNoPage) {
		return executeQuery(() -> {
			OrderMark orderMark = new OrderMark();
			orderMark.setOrderNo(orderNoPage.getOrderNo());
			List<OrderMark> orderMarkList = orderMarkMapper.query(orderMark);
			if (null != orderMarkList && !orderMarkList.isEmpty()) {
				OrderMarkInfo orderMarkInfo = new OrderMarkInfo();
				BeanUtils.copyProperties(orderMarkList.get(0), orderMarkInfo);
				return orderMarkInfo;
			}
			return null;
		});
	}

	@Override
	public RestResult<String> modifyFlag(OrderTagRequest orderTagRequest) {
		OperateModel operate = new OperateModel(OperatorActionEnum.MODIFY_FLAG, orderTagRequest.getSerialNo());
		operate.setOperator(orderTagRequest.getOperator());
		operate.setOperatorName(orderTagRequest.getOperateName());
		return executeOperate(operate, new TemplateService<String, OrderModel>() {
			@Override
			public OrderModel init() {
				OrderModel orderModel = new OrderModel();
				orderModel.setOrderNo(orderTagRequest.getOrderNo());
				return orderModel;
			}

			@Override
			public String process(OrderModel model) {
				model.setOrderTag(OrderTagEnum.getByCode(orderTagRequest.getOrderTag()).getCode());
				return model.getOrderNo();
			}

		});
	}

	@Override
	public RestResult<OrderInvoceInfo> invoiceQuery(OrderNoPage orderNoPage) {
		return executeQuery(() -> {
			OrderInvoice orderInvoice = new OrderInvoice();
			orderInvoice.setOrderNo(orderNoPage.getOrderNo());
			List<OrderInvoice> orderInvoiceList = orderInvoiceMapper.query(orderInvoice);
			if (null != orderInvoiceList && !orderInvoiceList.isEmpty()) {
				OrderInvoceInfo orderInvoceInfo = new OrderInvoceInfo();
				BeanUtils.copyProperties(orderInvoiceList.get(0), orderInvoceInfo);
				return orderInvoceInfo;
			}
			return null;
		});
	}

	@Override
	public RestResult<Map<String, Long>> queryFirstPaymentCount(OrderStatisticsRequest request) {
		List<Map<String, Object>> list = orderMapper.queryFirstPaymentCount(request);
		return RestResult.success(toCountMap(list));
	}

	@Override
	public RestResult<Map<String, Long>> queryOrderCount(OrderStatisticsRequest request) {
		List<Map<String, Object>> list = orderMapper.queryOrderCount(request);
		return RestResult.success(toCountMap(list));
	}

    @Override
    public RestResult<Map<String, Map<String, Object>>> queryOrderGmv(OrderStatisticsRequest request) {
        Map<String, Map<String, Object>> result = Maps.newHashMap();
        List<Map<String, Object>> list = orderMapper.queryOrderGmv(request);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(map -> {
                String channelCode = (String) map.get("channelCode");
                channelCode = StringUtils.isBlank(channelCode) ? "others" : channelCode;
                Map<String, Object> typeMap = result.get(channelCode);
                if (null == typeMap) {
                    typeMap = Maps.newHashMap();
                    result.put(channelCode, typeMap);
                }
                String goodsType = (String) map.get("goodsType");
                goodsType = StringUtils.isBlank(goodsType) ? "others" : goodsType;
                Long totalCount = (Long) map.get("totalCount");
                totalCount = null == totalCount ? 0L : totalCount;
                String totalAmountStr = (String) map.get("totalAmount");
                totalAmountStr = StringUtils.isBlank(totalAmountStr) ? "0" : totalAmountStr;
                BigDecimal totalAmount = new BigDecimal(totalAmountStr);
                String countKey = goodsType + ":TOTAL_COUNT";
                String amountKey = goodsType + ":TOTAL_AMOUNT";
                if (null == typeMap.get(countKey)) {
                    typeMap.put(countKey, 0L);
                }
                typeMap.put(countKey, ((Long) typeMap.get(countKey)) + totalCount);
                if (null == typeMap.get(amountKey)) {
                    typeMap.put(amountKey, BigDecimal.ZERO);
                }
                typeMap.put(amountKey, ((BigDecimal) typeMap.get(amountKey)).add(totalAmount));
            });
        }
        return RestResult.success(result);
    }

	private Map<String, Long> toCountMap(List<Map<String, Object>> list) {
		Map<String, Long> result = Maps.newHashMap();
		if (CollectionUtils.isNotEmpty(list)) {
			list.forEach(map -> {
				String channelCode = (String) map.get("channelCode");
				channelCode = StringUtils.isBlank(channelCode) ? "others" : channelCode;
				Long count = (Long) map.get("count");
				count = null == count ? 0L : count;
				result.put(channelCode, count);
			});
		}
		return result;
	}

	@Override
	public RestResult<List<JSONObject>> querySubmitOrderUserLeft(OrderStatisticsRequest request) {
		return RestResult.success(orderMapper.querySubmitOrderUserLeft(request));
	}

	@Override
	public List<OrderResponse> queryBycommodityCode(String commodityCode,Date settStartTime, Date settEndTime) {
		return orderMapper.queryBycommodityCode(commodityCode,settStartTime,settEndTime);
	}

	@Override
	public List<OrderResponse> queryBycommodityCodeNumber(String commodityCode, Date settStartTime, Date settEndTime) {
		return orderMapper.queryBycommodityCodeNumber(commodityCode,settStartTime,settEndTime);
	}
}
